﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using Transfer.CommonUnit;
using Transfer.Utils;

namespace Transfer.SingleFloor
{
	public class ElementsTransformControler
	{
		public ElementsTransformControler(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
			this.m_ClassificationBatchConverterData = new ElementsTransformControler.ClassificationBatchConverterData();
			string pathName = this.m_Revit.Application.ActiveUIDocument.Document.PathName;
			ElementId id = this.m_Revit.Application.ActiveUIDocument.ActiveView.Id;
			this.m_SelectionSetManager = new SelectionSetManager(pathName, id);
		}

		public Result ConvertElements()
		{
			string text = "";
			if (this.m_SelectionSetManager.FileIsNotSaved() && !this.SaveNewFile())
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			this.m_SelectionSetManager.ReadInfoFromFile(this.m_Revit.Application.ActiveUIDocument.Document);
			TransformTypeForm transformTypeForm;
			for (;;)
			{
				transformTypeForm = new TransformTypeForm(this.m_Revit, this.m_SelectionSetManager);
				if (transformTypeForm.ShowDialog() != DialogResult.OK)
				{
					break;
				}
				if (transformTypeForm.DialogResultIsSelecteElement)
				{
					try
					{
						List<Element> list = new List<Element>();
						if (!this.SelelctElements(ref list, ref text))
						{
							continue;
						}
						List<ComponentType> typeList = this.GetTypeList(list);
						List<ElementId> list2 = new List<ElementId>();
						foreach (Element element in list)
						{
							list2.Add(element.Id);
						}
						SelectionSet selSet = new SelectionSet("选择集", list2, typeList);
						this.m_SelectionSetManager.AddSelectionSet(selSet);
						continue;
					}
					catch (Exception)
					{
						return Autodesk.Revit.UI.Result.Cancelled;
					}
				}
				goto IL_F4;
			}
			return Autodesk.Revit.UI.Result.Cancelled;
			IL_F4:
			this.m_SelectionSetManager.WriteInfoToFile();
			List<Element> elements = transformTypeForm.SelectElements();
			this.m_SelectTypeList = transformTypeForm.SelectedTypeList();
			bool isByWall = transformTypeForm.IsByWall();
			this.m_Tolerance = transformTypeForm.Tolerance();
			if (!this.FilterTransformElements(elements, ref text))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			Transform transform = new Transform(Transform.Identity);
			if (!this.GetTransform(isByWall, true, ref transform))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			for (;;)
			{
				Transform transform2 = new Transform(Transform.Identity);
				if (!this.GetTransform(isByWall, false, ref transform2))
				{
					break;
				}
				this.m_TransFormMatrix = transform2 * transform.Inverse;
				Transaction transaction = new Transaction(this.m_Revit.Application.ActiveUIDocument.Document);
				transaction.Start("Transform");
				Result result;
				try
				{
					this.TrasformElements();
					transaction.Commit();
					continue;
				}
				catch (Exception ex)
				{
					transaction.RollBack();
					string message = ex.Message;
					result = Autodesk.Revit.UI.Result.Failed;
				}
				return result;
			}
			return Autodesk.Revit.UI.Result.Cancelled;
		}

		private bool SaveNewFile()
		{
			DialogResult dialogResult = MessageBox.Show("当前文件尚未保存，保存之后方可使用此命令，是否保存？", "盈建科提示", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
			if (DialogResult.Yes == dialogResult)
			{
				SaveFileDialog saveFileDialog = new SaveFileDialog();
				saveFileDialog.Filter = "Revit文件|*.rvt";
				saveFileDialog.RestoreDirectory = true;
				saveFileDialog.FilterIndex = 1;
				if (saveFileDialog.ShowDialog() == DialogResult.OK)
				{
					string fileName = saveFileDialog.FileName;
					SaveAsOptions saveAsOptions = new SaveAsOptions();
					saveAsOptions.OverwriteExistingFile = true;
					RevitVersionFuncs.SaveAs(this.m_Revit.Application.ActiveUIDocument.Document, fileName, saveAsOptions);
					this.m_SelectionSetManager.SetDocumentPathName(fileName);
					return true;
				}
			}
			return false;
		}

		private bool FindCopyTypeByName(string findName)
		{
			return this.m_SelectTypeList.FindIndex((ComponentType t) => t.m_Category.CompareTo(findName) == 0) >= 0;
		}

		private void TrasformElements()
		{
			ViewDetailLevel detailLevel = this.m_Revit.Application.ActiveUIDocument.ActiveView.DetailLevel;
			this.m_Revit.Application.ActiveUIDocument.ActiveView.DetailLevel = (ViewDetailLevel)3;
			GeneralElementsTransfer generalElementsTransfer = new GeneralElementsTransfer(this.m_Revit, this.m_TransFormMatrix);
			generalElementsTransfer.CoypWindows = (this.FindCopyTypeByName("Windows") || this.FindCopyTypeByName("窗"));
			generalElementsTransfer.CopyDoors = (this.FindCopyTypeByName("Doors") || this.FindCopyTypeByName("门"));
			generalElementsTransfer.CopyOpenings = (this.FindCopyTypeByName("Rectangular Straight Wall Opening") || this.FindCopyTypeByName("矩形直墙洞口") || this.FindCopyTypeByName("Rectangular Arc Wall Opening") || this.FindCopyTypeByName("矩形弧墙洞口"));
			FamilyInstanceTransfer familyInstanceTransfer = new FamilyInstanceTransfer(this.m_Revit, this.m_TransFormMatrix, this.m_Tolerance);
			generalElementsTransfer.TrasformGeneralElements(this.m_ClassificationBatchConverterData.GeneralHostElemtntsId);
			generalElementsTransfer.TrasformGeneralElements(this.m_ClassificationBatchConverterData.GeneralFamilyInstancesId);
			generalElementsTransfer.TrasformGeneralElements(this.m_ClassificationBatchConverterData.RoomsSpacesZonesAreasId);
			generalElementsTransfer.TrasformGeneralElements(this.m_ClassificationBatchConverterData.AttachedToCeilingOfFamilyInstancesId);
			familyInstanceTransfer.TransformFamilyInstance(this.m_ClassificationBatchConverterData.DoorsWindowsId, -1);
			familyInstanceTransfer.TransformFamilyInstance(this.m_ClassificationBatchConverterData.AttachedToWallOfFamilyInstancesId, 1);
			familyInstanceTransfer.TransformFamilyInstance(this.m_ClassificationBatchConverterData.AttachedToSurfaceOfFamilyInstancesId, 5);
			familyInstanceTransfer.TrasformDimensions(this.m_ClassificationBatchConverterData.DimensionsId);
			familyInstanceTransfer.TransformTags(this.m_ClassificationBatchConverterData.TagId);
			this.m_Revit.Application.ActiveUIDocument.ActiveView.DetailLevel = detailLevel;
		}

		private bool FilterTransformElements(List<Element> elements, ref string message)
		{
			try
			{
				for (int i = 0; i < elements.Count; i++)
				{
					Element element = elements[i];
					if (this.IsValidType(element))
					{
						if (element.GetType() == typeof(Room) || element.GetType() == typeof(Space) || element.GetType() == typeof(Zone) || element.GetType() == typeof(Area))
						{
							this.m_ClassificationBatchConverterData.RoomsSpacesZonesAreasId.Add(element.Id);
						}
						else if (element.GetType() == typeof(RoomTag) || element.GetType() == typeof(SpaceTag) || element.GetType() == typeof(AreaTag) || element.GetType() == typeof(IndependentTag))
						{
							this.m_ClassificationBatchConverterData.TagId.Add(element.Id);
						}
						else if (element.Category.Id.IntegerValue == -2000260)
						{
							this.m_ClassificationBatchConverterData.DimensionsId.Add(element.Id);
						}
						else if (element.GetType() == typeof(FamilyInstance))
						{
							FamilyInstance familyInstance = element as FamilyInstance;
							if (familyInstance.Category.Id.IntegerValue == -2000023 || familyInstance.Category.Id.IntegerValue == -2000014 || familyInstance.Category.Id.IntegerValue == -2000997 || familyInstance.Category.Id.IntegerValue == -2000999)
							{
								if (!this.IsTransformWall())
								{
									this.m_ClassificationBatchConverterData.DoorsWindowsId.Add(element.Id);
								}
							}
							else
							{
								Parameter parameter = familyInstance.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_HOSTING_BEHAVIOR);
								if (parameter != null)
								{
									int num = parameter.AsInteger();
									if (num == 0)
									{
										this.m_ClassificationBatchConverterData.GeneralHostElemtntsId.Add(element.Id);
									}
									else if (num == 1)
									{
										this.m_ClassificationBatchConverterData.AttachedToWallOfFamilyInstancesId.Add(element.Id);
									}
									else if (num == 3)
									{
										this.m_ClassificationBatchConverterData.AttachedToCeilingOfFamilyInstancesId.Add(element.Id);
									}
									else if (num == 5)
									{
										this.m_ClassificationBatchConverterData.AttachedToSurfaceOfFamilyInstancesId.Add(element.Id);
									}
								}
							}
						}
						else
						{
							this.m_ClassificationBatchConverterData.GeneralHostElemtntsId.Add(element.Id);
						}
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private bool IsTransformWall()
		{
			using (List<ComponentType>.Enumerator enumerator = this.m_SelectTypeList.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current.m_Type.CompareTo("Wall") == 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool IsValidType(Element element)
		{
			string name = element.GetType().Name;
			string name2 = element.Category.Name;
			ComponentType componentType = new ComponentType(name, name2);
			return this.m_SelectTypeList.FindIndex((ComponentType t) => t.IsEquals(componentType)) >= 0;
		}

		private bool GetTransform(bool isByWall, bool isFirst, ref Transform transform)
		{
			if (isByWall)
			{
				return this.GetTransformByWalls(isFirst, ref transform);
			}
			return this.GetTransformByPoints(isFirst, ref transform);
		}

		private bool GetTransformByPoints(bool isFirst, ref Transform transform)
		{
			string str;
			if (isFirst)
			{
				str = "源";
			}
			else
			{
				str = "目标";
			}
			XYZ xyz = null;
			if (!this.SelelctPosision(ref xyz, "选择" + str + "区域第1定位点"))
			{
				return false;
			}
			XYZ xyz2 = null;
			if (!this.SelelctPosision(ref xyz2, "选择" + str + "区域第2定位点"))
			{
				return false;
			}
			XYZ xyz3 = (xyz2 - xyz).Normalize();
			XYZ xyz4 = null;
			if (!this.SelelctPosision(ref xyz4, "选择" + str + "区域第3定位点"))
			{
				return false;
			}
			XYZ xyz5 = (xyz4 - xyz).Normalize();
			XYZ xyz6 = xyz3.CrossProduct(xyz5).Normalize();
			XYZ basisY = xyz6.CrossProduct(xyz3).Normalize();
			transform.Origin = xyz;
			transform.BasisX = xyz3;
			transform.BasisY = basisY;
			transform.BasisZ = xyz6;
			return true;
		}

		private bool SelelctPosision(ref XYZ pt, string statusPrompt)
		{
			try
			{
				XYZ xyz = this.m_Revit.Application.ActiveUIDocument.Selection.PickPoint(statusPrompt);
				pt = new XYZ(xyz.X, xyz.Y, 0.0);
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private bool GetTransformByWalls(bool isFirst, ref Transform transform)
		{
			string str;
			if (isFirst)
			{
				str = "源";
			}
			else
			{
				str = "目标";
			}
			XYZ point = null;
			Line line = null;
			if (!this.SelelctWallByPoint(ref line, ref point, "选择" + str + "区域第1根直线墙"))
			{
				return false;
			}
			XYZ point2 = null;
			Line line2 = null;
			if (!this.SelelctWallByPoint(ref line2, ref point2, "选择" + str + "区域与第1根墙相交的第2根直线墙"))
			{
				return false;
			}
			IntersectionResultArray intersectionResultArray;
			if (line.Intersect(line2, out intersectionResultArray) != 8)
			{
				return false;
			}
			XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
			XYZ xyz = Geometry.CalculateFootPoint(line, point);
			XYZ xyz2 = Geometry.CalculateFootPoint(line2, point2);
			XYZ xyz3 = (xyz - xyzpoint).Normalize();
			XYZ xyz4 = (xyz2 - xyzpoint).Normalize();
			XYZ xyz5 = xyz3.CrossProduct(xyz4);
			XYZ basisY = xyz5.CrossProduct(xyz3);
			transform.Origin = xyzpoint;
			transform.BasisX = xyz3;
			transform.BasisY = basisY;
			transform.BasisZ = xyz5;
			return true;
		}

		private bool SelelctWallByPoint(ref Line line, ref XYZ pt, string statusPrompt)
		{
			bool result;
			try
			{
				Selection selection = this.m_Revit.Application.ActiveUIDocument.Selection;
				Reference reference;
				LocationCurve locationCurve;
				for (;;)
				{
					reference = selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, new Transfer.SingleFloor.WallFilter(), statusPrompt);
					Element element = this.m_Revit.Application.ActiveUIDocument.Document.GetElement(reference);
					if (!(element.GetType() != typeof(Wall)))
					{
						locationCurve = (element.Location as LocationCurve);
						if (locationCurve != null && !(locationCurve.Curve.GetType() != typeof(Line)))
						{
							break;
						}
					}
				}
				Line curve = locationCurve.Curve as Line;
				XYZ xyz = curve.GetEndPoint(0);
				xyz = new XYZ(xyz.X, xyz.Y, 0.0);
				XYZ xyz2 = curve.GetEndPoint(1);
				xyz2 = new XYZ(xyz2.X, xyz2.Y, 0.0);
				line = YJKLineEx.YJKGetBound(xyz, xyz2);
				pt = new XYZ(reference.GlobalPoint.X, reference.GlobalPoint.Y, 0.0);
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private List<ComponentType> GetTypeList(List<Element> elements)
		{
			List<ComponentType> list = new List<ComponentType>();
			foreach (Element element in elements)
			{
				string name = element.GetType().Name;
				string name2 = element.Category.Name;
				ComponentType componentType = new ComponentType(name, name2);
				if (list.FindIndex((ComponentType t) => t.IsEquals(componentType)) < 0)
				{
					list.Add(componentType);
				}
			}
			return list;
		}

		private bool SelelctElements(ref List<Element> elements, ref string message)
		{
			Transaction transaction = null;
			Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			double elevation = this.m_Revit.Application.ActiveUIDocument.ActiveView.GenLevel.Elevation;
			transaction = new Transaction(document);
			transaction.Start("SelelctElements");
			try
			{
				IList<Reference> list = this.m_Revit.Application.ActiveUIDocument.Selection.PickObjects((Autodesk.Revit.UI.Selection.ObjectType)1);
				for (int i = 0; i < list.Count; i++)
				{
					Element element = document.GetElement(list[i]);
					if (element.GetType() == typeof(RoomTag) || element.GetType() == typeof(SpaceTag) || element.GetType() == typeof(AreaTag) || element.GetType() == typeof(IndependentTag))
					{
						elements.Add(element);
					}
					else if (element.Category.Id.IntegerValue == -2000260)
					{
						elements.Add(element);
					}
					else if (!(element.GetType() == typeof(Autodesk.Revit.DB.Group)) && !this.IsBelowTheElevation(element, elevation))
					{
						elements.Add(element);
					}
				}
			}
			catch (Exception)
			{
				if (transaction != null && transaction.HasStarted() && !transaction.HasEnded())
				{
					transaction.RollBack();
				}
				return false;
			}
			transaction.Commit();
			return true;
		}

		private bool IsBelowTheElevation(Element element, double elevation)
		{
			return false;
		}

		private ExternalCommandData m_Revit;

		private Transform m_TransFormMatrix;

		private ElementsTransformControler.ClassificationBatchConverterData m_ClassificationBatchConverterData;

		private List<ComponentType> m_SelectTypeList = new List<ComponentType>();

		private SelectionSetManager m_SelectionSetManager;

		private double m_Tolerance;

		private class ClassificationBatchConverterData
		{
			public List<ElementId> GeneralHostElemtntsId
			{
				get
				{
					return this.m_GeneralHostElemtntsId;
				}
				set
				{
					this.m_GeneralHostElemtntsId = value;
				}
			}

			public List<ElementId> GeneralFamilyInstancesId
			{
				get
				{
					return this.m_GeneralFamilyInstancesId;
				}
				set
				{
					this.m_GeneralFamilyInstancesId = value;
				}
			}

			public List<ElementId> RoomsSpacesZonesAreasId
			{
				get
				{
					return this.m_RoomsSpacesZonesAreasId;
				}
				set
				{
					this.m_RoomsSpacesZonesAreasId = value;
				}
			}

			public List<ElementId> TagId
			{
				get
				{
					return this.m_TagId;
				}
				set
				{
					this.m_TagId = value;
				}
			}

			public List<ElementId> DoorsWindowsId
			{
				get
				{
					return this.m_DoorsWindowsId;
				}
				set
				{
					this.m_DoorsWindowsId = value;
				}
			}

			public List<ElementId> AttachedToSurfaceOfFamilyInstancesId
			{
				get
				{
					return this.m_AttachedToSurfaceOfFamilyInstancesId;
				}
				set
				{
					this.m_AttachedToSurfaceOfFamilyInstancesId = value;
				}
			}

			public List<ElementId> AttachedToWallOfFamilyInstancesId
			{
				get
				{
					return this.m_AttachedToWallOfFamilyInstancesId;
				}
				set
				{
					this.m_AttachedToWallOfFamilyInstancesId = value;
				}
			}

			public List<ElementId> AttachedToCeilingOfFamilyInstancesId
			{
				get
				{
					return this.m_AttachedToCeilingOfFamilyInstancesId;
				}
				set
				{
					this.m_AttachedToCeilingOfFamilyInstancesId = value;
				}
			}

			public List<ElementId> DimensionsId
			{
				get
				{
					return this.m_DimensionsId;
				}
				set
				{
					this.m_DimensionsId = value;
				}
			}

			public ClassificationBatchConverterData()
			{
				this.m_GeneralHostElemtntsId = new List<ElementId>();
				this.m_GeneralFamilyInstancesId = new List<ElementId>();
				this.m_RoomsSpacesZonesAreasId = new List<ElementId>();
				this.m_TagId = new List<ElementId>();
				this.m_DoorsWindowsId = new List<ElementId>();
				this.m_AttachedToSurfaceOfFamilyInstancesId = new List<ElementId>();
				this.m_AttachedToWallOfFamilyInstancesId = new List<ElementId>();
				this.m_AttachedToCeilingOfFamilyInstancesId = new List<ElementId>();
				this.m_DimensionsId = new List<ElementId>();
			}

			~ClassificationBatchConverterData()
			{
				this.m_GeneralHostElemtntsId.Clear();
				this.m_GeneralHostElemtntsId = null;
				this.m_GeneralFamilyInstancesId.Clear();
				this.m_GeneralFamilyInstancesId = null;
				this.m_RoomsSpacesZonesAreasId.Clear();
				this.m_RoomsSpacesZonesAreasId = null;
				this.m_TagId.Clear();
				this.m_TagId = null;
				this.m_DoorsWindowsId.Clear();
				this.m_DoorsWindowsId = null;
				this.m_AttachedToSurfaceOfFamilyInstancesId.Clear();
				this.m_AttachedToSurfaceOfFamilyInstancesId = null;
				this.m_AttachedToWallOfFamilyInstancesId.Clear();
				this.m_AttachedToWallOfFamilyInstancesId = null;
				this.m_AttachedToCeilingOfFamilyInstancesId.Clear();
				this.m_AttachedToCeilingOfFamilyInstancesId = null;
				this.m_DimensionsId.Clear();
				this.m_DimensionsId = null;
			}

			private List<ElementId> m_GeneralHostElemtntsId;

			private List<ElementId> m_GeneralFamilyInstancesId;

			private List<ElementId> m_RoomsSpacesZonesAreasId;

			private List<ElementId> m_TagId;

			private List<ElementId> m_DoorsWindowsId;

			private List<ElementId> m_AttachedToSurfaceOfFamilyInstancesId;

			private List<ElementId> m_AttachedToWallOfFamilyInstancesId;

			private List<ElementId> m_AttachedToCeilingOfFamilyInstancesId;

			private List<ElementId> m_DimensionsId;
		}
	}
}
